package com.stray.crawl.model.dao;

import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.regex.Pattern;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.codehaus.jackson.JsonFactory;
import org.codehaus.jackson.map.ObjectMapper;

import com.stray.crawl.model.CrawlPlan;
import com.stray.crawl.model.PlanUrl;

public abstract class PlanRepository {

	protected final Log log = LogFactory.getLog(this.getClass());
	protected UrlFormatter formatter = new UrlFormatter();

	protected void savePlan(CrawlPlan plan) {
		// not available by default
	}

	protected abstract Collection<CrawlPlan> getPlans();

	protected abstract Collection<CrawlPlan> getGenericPlans();

	protected abstract Collection<CrawlPlan> getPlansByHost(String host);

	protected abstract CrawlPlan getPlanByUrl(PlanUrl url);

	public boolean buildSchema() {
		return true;
	}

	public void importPlans(String path) {
		File f = new File(path);
		File[] files = f.listFiles();
		ObjectMapper mapper = new ObjectMapper(new JsonFactory());

		if (files != null) {
			for (File file : files) {
				try {
					CrawlPlan plan = mapper.readValue(file, CrawlPlan.class);
					savePlan(plan);
				} catch (Exception ex) {
					log.info("Fail to import file : " + file, ex);
				}
			}
		}
	}

	public void exportPlans(String path) {
		File f = new File(path);
		ObjectMapper mapper = new ObjectMapper(new JsonFactory());

		List<CrawlPlan> list = new ArrayList<CrawlPlan>();

		Collection<CrawlPlan> plans = this.getPlans();
		Collection<CrawlPlan> gPlans = this.getGenericPlans();

		if (plans != null) {
			list.addAll(plans);
		}
		if (gPlans != null) {
			list.addAll(gPlans);
		}

		for (CrawlPlan plan : list) {
			try {
				File file = new File(f, plan.getId() + "." + plan.getName() + ".json");
				mapper.writeValue(file, plan);
			} catch (Exception ex) {
				log.info("Fail to export plan : " + plan, ex);
			}
		}
	}

	public CrawlPlan findMatchCrawlPlan(String url) {
		PlanUrl u = findMatchUrlPattern(url);
		return u != null ? getPlanByUrl(u) : null;
	}

	protected PlanUrl findMatchUrlPattern(String accessUrl) {
		if (accessUrl == null || accessUrl.isEmpty()) {
			return null;
		}

		accessUrl = formatter.sortAccessUrlOrder(accessUrl);
		String host = formatter.extractHost(accessUrl);

		Collection<CrawlPlan> plans = getPlansByHost(host);

		for (CrawlPlan plan : plans) {
			for (PlanUrl url : plan.getUrls()) {
				Pattern pattern = formatter.compilePattern(url);
				
				System.out.println("pattern : " + pattern);

				if (pattern.matcher(accessUrl).matches()) {
					return url;
				}
			}
		}

		Collection<CrawlPlan> genericPlans = getGenericPlans();
		for (CrawlPlan plan : genericPlans) {
			for (PlanUrl url : plan.getUrls()) {
				Pattern pattern = formatter.compilePattern(url);

				if (pattern.matcher(accessUrl).matches()) {
					return url;
				}
			}
		}

		return null;
	}

}